import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.SwingWorker;
import javax.swing.Timer;

/**
 * Proof of Concept.
 * Start, stop, pause, resume and control speed of an algorithm.
 *
 * @author Vianney DUPOY DE GUITARd
 * @version r0
 *
 */
public class CopieDeWorkerTest extends SwingWorker<Void, Void> implements ActionListener {

    /** Timer shortest delay. */
    private static final int MIN_DELAY = 2;

    /** The main timer. */
    private Timer   timer = new Timer((int) Math.pow(MIN_DELAY, 9), this);

    /** The lock shared between the thread and the timer (CPU optimization). */
    private Object  timerLock = new Object();

    /** Always true, used to make an infinite loop. */
    private boolean running = true;

    /** Help to determine if the timer is paused or not. */
    private boolean paused;

    /**
     * Random algorithm.
     * @return nothing.
     * @throws Exception in case of algorithm failure.
     */
    @Override
    protected Void doInBackground() throws Exception {
        // Infinite loop.
        while (true) {
            // Do nothing until the timer notifies this thread.
            synchronized (timerLock) {
                timerLock.wait();
            }
            System.out.println("tick");
        }
    }

    /**
     * Action triggered at each timer 'tick'.
     * @param e : triggered event (not used).
     */
    @Override
    public void actionPerformed(final ActionEvent e) {
        // Notifies the algorithm it can continue.
        synchronized (timerLock) {
            timerLock.notify();
        }
    }

    /** Starts the timer, and thus the algorithm. */
    public void start() {
        timer.start();
    }

    /** Stops the timer and resets the algorithm. */
    public void stop() {
        paused = false;
        timer.stop();
    }

    /** Pauses the timer and algorithm. */
    public void pause() {
        if (timer.isRunning()) {
            timer.stop();
            paused = true;
        }
    }

    /** Restarts the timer and algorithm. */
    public void restart() {
        timer.start();
        paused = false;
    }

    /** @return true or false whether the algorithm is paused or not. */
    public boolean isPaused() {
        return paused;
    }

    /** @return true or false whether the algorithm and timer are running or not. */
    public boolean isRunning() {
        return timer.isRunning() && running;
    }

    /**
     * Define a new timer delay.
     * @param pDelay : new delay.
     */
    public void setDelay(final int pDelay) {
        timer.setDelay(pDelay);
    }

    /** @return the min delay. */
    public int getMinDelay() {
        return MIN_DELAY;
    }

    /**
     * Entry point.
     * @param args : not used.
     */
    public static void main(final String[] args) {
        final CopieDeWorkerTest testClass = new CopieDeWorkerTest();
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        testClass.execute();
        frame.setVisible(true);
        testClass.start();
    }
}
